#include "stdafx.h"
#include "A2DImage.h"

UINT RoundUpToPowerOfTwo(UINT value)
{
	UINT result = 1;
	for (int i = 0; i < 32; i++)
	{
		result = 1 << i;
		if (result >= value)
			break;
	}
	return result;
}

//////////////////////////////////////////////////////////////////////////

A2DImage::A2DImage( A2DDevice &device ) 
	: A2DSubscriber(device)
{

}

bool A2DImage::LoadFromFile( LPCWSTR fileName )
{
	CAtlFile file;
	if (file.Create(fileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING) != S_OK)
		return false;
	ULONGLONG fileSize;
	if (file.GetSize(fileSize) != S_OK)
		return false;

	CAtlFileMapping<BYTE> fileMapping;
	if (fileMapping.MapFile(file) != S_OK)
		return false;

	return LoadFromMemory(fileMapping, (DWORD)fileSize);
}

bool A2DImage::LoadFromMemory( LPVOID data, DWORD size )
{
	bool loaded = (
		LoadAsJPEG(data, size)
	);

	if (loaded)
		return true;
	else
	{
		m_d3dTex.Release();
		return false;
	}
}

bool A2DImage::CreateTexture( UINT width, UINT height )
{
	CComPtr<IDirect3DDevice9> d3dDev = GetD3DDevice();
	if (d3dDev == nullptr)
		return false;

	UINT texW = RoundUpToPowerOfTwo(width);
	UINT texH = RoundUpToPowerOfTwo(height);
	CComPtr<IDirect3DTexture9> d3dTex;
	if (d3dDev->CreateTexture(texW, texH, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &d3dTex, nullptr) != S_OK)
		return false;

	m_d3dTex = d3dTex;
	m_size = CSize(width, height);
	m_texSize = CSize(texW, texH);
	return true;
}

bool A2DImage::Lock( LPBYTE &buffer, int &pitch )
{
	if (m_d3dTex == nullptr)
		return false;

	D3DLOCKED_RECT lockedRect;
	if (m_d3dTex->LockRect(0, &lockedRect, nullptr, D3DLOCK_NO_DIRTY_UPDATE) != S_OK)
		return false;

	buffer = (LPBYTE)lockedRect.pBits;
	pitch = lockedRect.Pitch;
	return true;
}

void A2DImage::Unlock( void )
{
	if (m_d3dTex == nullptr)
		return;

	HRESULT hr = m_d3dTex->UnlockRect(0);
	ATLASSERT(hr == S_OK);
}
